/*=============================================================================
*
*   Copyright (C) 2020 All rights reserved.
*
*   Filename:		test_plot.cpp
*
*   Author: Wang Zhecheng - wangzhecheng@yeah.net
*
*   Date: 2020-02-29 01:46
*
*   Last Editors: Wang Zhecheng - wangzhecheng@yeah.net
*
*   Last modified:	2020-08-31 04:23
*
*   Description:
*
=============================================================================*/
#define BOOST_AUTO_TEST_MAIN

#include "../include/fem.hpp"
#include "../include/implicit_solver.hpp"
#include "../include/incremental_load.hpp"
#include "../include/model/model.hpp"
#include "../include/solid.hpp"
#include "../include/static_equation.hpp"
#include <boost/test/included/unit_test.hpp>

using  geoxfem::geometry::ShapeInterface;
using geoxfem::model::Model;
using geoxfem::arithmetic;
using geoxfem;

LOGGING_REGISTER()

BOOST_AUTO_TEST_CASE(test_case1) {
  using Shape = ShapeInterface<plane_stress, mpl1>;

  /*variables{{{*/
  log::log_init(log::severity_level::info);

  Point2D p1(1, 1), p2(2, 5), p3(4, 3), p4(8, -1), p5(7, -4), p6(5, 1),
    p7(4, -2), p8(0.5, 4), p9(-2, 2), p10(0, 0), p11(1, -3), p12(-2, -2.5),
    p13(5, 6), p14(4, -5), p15(-3, 0.5), p16(0.7, 6), p17(-1.5, 3.5),
    p18(-1.2, 7);
  Model<fem, solid, plane_stress, static_equation, implicit_solver,
        incremental_load, mpl1>
    model;

  model.register_type();

  p1.setIndex(1);
  model.append(p1);
  p2.setIndex(2);
  model.append(p2);
  p3.setIndex(3);
  model.append(p3);
  p4.setIndex(4);
  model.append(p4);
  p5.setIndex(5);
  model.append(p5);
  p6.setIndex(6);
  model.append(p6);
  p7.setIndex(7);
  model.append(p7);
  p8.setIndex(8);
  model.append(p8);
  p9.setIndex(9);
  model.append(p9);
  p10.setIndex(10);
  model.append(p10);
  p11.setIndex(11);
  model.append(p11);
  p12.setIndex(12);
  model.append(p12);
  p13.setIndex(13);
  model.append(p13);
  p14.setIndex(14);
  model.append(p14);
  p15.setIndex(15);
  model.append(p15);
  p16.setIndex(16);
  model.append(p16);
  p17.setIndex(17);
  model.append(p17);
  p18.setIndex(18);
  model.append(p18);

  /*}}}*/
  /* segments{{{*/

  auto seg1  = Shape::getFactory().create("segment", {p8, p9});
  auto pseg1 = model.append(seg1, model.getMesh());
  BOOST_CHECK_CLOSE(pseg1->getArea(),
                    boost::geometry::length(pseg1->toSegment()), 1e-1);

  auto seg2  = Shape::getFactory().create("Segment", {p4, p13});
  auto pseg2 = model.append(seg2, model.getMesh());
  BOOST_CHECK_CLOSE(pseg2->getArea(),
                    boost::geometry::length(pseg2->toSegment()), 1e-1);

  auto seg3  = Shape::getFactory().create("Segment", {p11, p14});
  auto pseg3 = model.append(seg3, model.getMesh());
  BOOST_CHECK_CLOSE(pseg3->getArea(),
                    boost::geometry::length(pseg3->toSegment()), 1e-1);

  auto seg4  = Shape::getFactory().create("Segment", {p15, p17});
  auto pseg4 = model.append(seg4, model.getMesh());
  BOOST_CHECK_CLOSE(pseg4->getArea(),
                    boost::geometry::length(pseg4->toSegment()), 1e-1);

  auto seg5  = Shape::getFactory().create("Segment", {p18, p13});
  auto pseg5 = model.append(seg5, model.getMesh());
  BOOST_CHECK_CLOSE(pseg5->getArea(),
                    boost::geometry::length(pseg5->toSegment()), 1e-1);

  auto seg6  = Shape::getFactory().create("Segment", {p9, p17});
  auto pseg6 = model.append(seg6, model.getMesh());
  BOOST_CHECK_CLOSE(pseg6->getArea(),
                    boost::geometry::length(pseg6->toSegment()), 1e-1);

  /*}}}*/
  /*triangles{{{*/

  auto tri1  = Shape::getFactory().create("Triangle", {p1, p2, p3});
  auto ptri1 = model.append(tri1, model.getMesh());
  BOOST_CHECK_CLOSE(ptri1->getArea(), boost::geometry::area(ptri1->toPolygon()),
                    1e-1);

  auto tri2  = Shape::getFactory().create("Triangle", {p10, p12, p11});
  auto ptri2 = model.append(tri2, model.getMesh());
  BOOST_CHECK_CLOSE(ptri2->getArea(), boost::geometry::area(ptri2->toPolygon()),
                    1e-1);

  auto tri3  = Shape::getFactory().create("Triangle", {p2, p3, p13});
  auto ptri3 = model.append(tri3, model.getMesh());
  BOOST_CHECK_CLOSE(ptri3->getArea(), boost::geometry::area(ptri3->toPolygon()),
                    1e-1);

  auto tri4  = Shape::getFactory().create("Triangle", {p7, p14, p5});
  auto ptri4 = model.append(tri4, model.getMesh());
  BOOST_CHECK_CLOSE(ptri4->getArea(), boost::geometry::area(ptri4->toPolygon()),
                    1e-1);

  auto tri5  = Shape::getFactory().create("Triangle", {p15, p12, p10});
  auto ptri5 = model.append(tri5, model.getMesh());
  BOOST_CHECK_CLOSE(ptri5->getArea(), boost::geometry::area(ptri5->toPolygon()),
                    1e-1);

  auto tri6  = Shape::getFactory().create("Triangle", {p17, p18, p16});
  auto ptri6 = model.append(tri6, model.getMesh());
  BOOST_CHECK_CLOSE(ptri6->getArea(), boost::geometry::area(ptri6->toPolygon()),
                    1e-1);

  /*}}}*/
  /*quadrangles{{{*/

  auto quad1  = Shape::getFactory().create("Quadrangle", {p4, p5, p6, p7});
  auto pquad1 = model.append(quad1, model.getMesh());
  BOOST_CHECK_CLOSE(pquad1->getArea(),
                    boost::geometry::area(pquad1->toPolygon()), 1e-1);

  auto quad2  = Shape::getFactory().create("Quadrangle", {p1, p3, p6, p7});
  auto pquad2 = model.append(quad2, model.getMesh());
  BOOST_CHECK_CLOSE(pquad2->getArea(),
                    boost::geometry::area(pquad2->toPolygon()), 1e-1);

  auto quad3  = Shape::getFactory().create("Quadrangle", {p7, p14, p1, p11});
  auto pquad3 = model.append(quad3, model.getMesh());

  auto quad4  = Shape::getFactory().create("Quadrangle", {p17, p8, p9, p16});
  auto pquad4 = model.append(quad4, model.getMesh());

  /*}}}*/

  bool if_plot = (boost::unit_test::framework::master_test_suite().argc < 2)
                   ? true
                   : std::stoi(std::string(
                     boost::unit_test::framework::master_test_suite().argv[1]));
  if(if_plot) {
    geoxfem::io::DataPloter plt;

    std::string line_cfg = " w l ls 1";
    std::string gp_cfg   = " w p pt 1 lc rgb \"red\"";
    plt.appendSetting("set view equal xyz");
    plt.appendSetting("set view 0,0");
    plt.appendSetting("set title \"gauss distribution and shape plot test\"");
    pseg1->plot(plt, line_cfg + " lc rgb \"yellow\"", gp_cfg);
    pseg2->plot(plt, line_cfg + " lc rgb \"yellow\"", gp_cfg);
    pseg3->plot(plt, line_cfg + " lc rgb \"yellow\"", gp_cfg);
    pseg4->plot(plt, line_cfg + " lc rgb \"yellow\"", gp_cfg);
    pseg5->plot(plt, line_cfg + " lc rgb \"yellow\"", gp_cfg);
    pseg6->plot(plt, line_cfg + " lc rgb \"yellow\"", gp_cfg);
    ptri1->plot(plt, line_cfg + " lc rgb \"black\"", gp_cfg);
    ptri2->plot(plt, line_cfg + " lc rgb \"black\"", gp_cfg);
    ptri3->plot(plt, line_cfg + " lc rgb \"black\"", gp_cfg);
    ptri4->plot(plt, line_cfg + " lc rgb \"black\"", gp_cfg);
    ptri5->plot(plt, line_cfg + " lc rgb \"black\"", gp_cfg);
    ptri6->plot(plt, line_cfg + " lc rgb \"black\"", gp_cfg);
    pquad1->plot(plt, line_cfg + " lc rgb \"green\" ", gp_cfg);
    pquad2->plot(plt, line_cfg + " lc rgb \"green\" ", gp_cfg);
    pquad3->plot(plt, line_cfg + " lc rgb \"green\" ", gp_cfg);
    pquad4->plot(plt, line_cfg + " lc rgb \"green\" ", gp_cfg);
  }
}
